/**
 * 
 */
package com.feib.stms.util;

import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.controller.StripesConstants;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

import com.feib.stms.model.Group;
import com.feib.stms.model.MenuItem;
import com.feib.stms.model.Role;
import com.feib.stms.model.User;
import com.feib.stms.security.core.userdetails.StmsUserDetailService;
import com.feib.stms.security.core.userdetails.StmsUserDetailsWrapper;
import com.feib.stms.service.UserService;

/**
 * @title (#)UserUtil.java<br>
 * @description <br>
 * @author Jimmy Liu<br>
 * @version 1.0.0 2010/11/25
 * @copyright Far Eastern International Bank Copyright (c) 2010<br>
 * @2010/11/14 create by Jimmy Liu<br>
 *
 */
public class UserUtil 
{

	protected static Logger logger = LoggerFactory.getLogger(UserUtil.class);
	
    public static final String ADMIN_ROLE = "ADMINISTRATOR";
	
	private static final ThreadLocal<HttpSession> _session = new ThreadLocal<HttpSession>();

    private static final ThreadLocal<HttpServletRequest> _request = new ThreadLocal<HttpServletRequest>();

    private static final ThreadLocal<HttpServletResponse> _response = new ThreadLocal<HttpServletResponse>();

    public static final String LOGIN_STAFF_OBJECT_KEY = "__LOGIN_USER_OBJECT_KEY";

    public static final String LOGIN_STAFF_MENU_KEY = "__LOGIN_USER_MENU_KEY";

    public static void setServletRequest(HttpServletRequest httpservletrequest)
    {
        _session.set(httpservletrequest.getSession());
        _request.set(httpservletrequest);
    }

    public static HttpServletRequest getServletRequest()
    {
        return (HttpServletRequest) _request.get();
    }

    public static void setServletResponse(HttpServletResponse httpservletresponse)
    {
        _response.set(httpservletresponse);
    }

    public static HttpServletResponse getServletResponse()
    {
        return (HttpServletResponse) _response.get();
    }
    
    public static void setSessionAttribute(String s, Object obj)
    {
        ((HttpSession) _session.get()).setAttribute(s, obj);
    }

    public static Object getSessionAttribute(String s)
    {
        if((HttpSession) _session.get() == null)
            return null;
        return ((HttpSession) _session.get()).getAttribute(s);
    }
	
	/**
     * 登入者物件
     * 
     * @return
     */
	public static User getUser()
	{
		/* 有登入才會抓到 User 物件*/
		if(null != SecurityContextHolder.getContext().getAuthentication())
		{
			Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			
			if ( principal instanceof StmsUserDetailsWrapper)
			{
				return ((StmsUserDetailsWrapper)principal).getUser();
			}
			else
			{

                // 從Session 取得登入資訊
                User user = (User) getSessionAttribute(LOGIN_STAFF_OBJECT_KEY);
                if(null != user)
                    return user;
                				
                // 取得 Login ID
                String userId = null;
                String groupNo = null;
                
                if(principal instanceof UserDetails)
                {
                    String[] userNameTemp = ((UserDetails) principal).getUsername().split(StmsUserDetailService.USERNAME_SPLIT_FORMAT);
                    userId = userNameTemp[1];
                    groupNo = userNameTemp[0];
                }
                else
                {
                    // 這裡一定會無法登入
                    userId = principal.toString();
                }
                
                // 取得 User 物件
                if (null != groupNo)
                {
                	UserService userService = (UserService) SpringContextUtil.getBean("userService");
                	user = userService.findLoginDataByUserIdGroupNo(userId, groupNo);
                	setSessionAttribute(LOGIN_STAFF_OBJECT_KEY, user);
                	if (null == user) {
                        String message = "群組代號  : " + groupNo + "，使用者名稱 : " + userId + "不存在!!";
                        logger.info(message);
                	}
                	
                	return user;
                }
			}
		}
		
		return null;
	}

    /**
     * 登入者帳號
     * 
     * @return
     */
    public static String getUserId()
    {
        User user = getUser();
        if(null == user)
            return null;
        else
            return user.getUserId();
    }
	
	/**
     * 登入者姓名
     * 
     * @return
     */
    public static String getUserName()
    {
        User user = getUser();
        if(null == user)
            return null;
        else
            return user.getUserName();
    }


    /**
     * 登入者群組
     * 
     * @return
     */
    public static Group getUserGroup()
    {
        User user = getUser();
        if(null == user)
            return null;
        else
            return user.getGroup();
    }
    
    @SuppressWarnings("unchecked")
	public static Map<MenuItem, Set<MenuItem>> getUserMenuItems()
    {
    	User user = getUser();
        if(null == user)
            return null;

        // 從 Session 中取得 Menus
        Map<MenuItem, Set<MenuItem>> userMenuItems = (Map<MenuItem, Set<MenuItem>>) ((HttpSession) _session.get()).getAttribute(LOGIN_STAFF_MENU_KEY);
        if (null == userMenuItems)
        {
            // 不存在，則由User Object 中取得，排序後，放入Session中
            userMenuItems = new TreeMap<MenuItem, Set<MenuItem>>(new Comparator<MenuItem>() {

				public int compare(MenuItem o1, MenuItem o2) {
					int o1No = (null == o1.getOrderNo() ? -1 : o1.getOrderNo().intValue());
                    int o2No = (null == o2.getOrderNo() ? -1 : o2.getOrderNo().intValue());
                    if (o1No == o2No)
                        return 0;
                    else if (o1No > o2No)
                        return 1;
                    else return -1;
				}
                
            });
            ((HttpSession) _session.get()).setAttribute(LOGIN_STAFF_MENU_KEY, userMenuItems);
            
            for(Iterator<Role> roles = user.getRoles().iterator(); roles.hasNext();)
            {
                Role role = (Role) roles.next();
                for(Iterator<MenuItem> menuItems = role.getMenuItems().iterator(); menuItems.hasNext();)
                {
                    MenuItem menuItem = (MenuItem) menuItems.next();
                    
                    if (null == menuItem.getEnabled() || false == menuItem.getEnabled().booleanValue())
                    {
                        // 此Menu disabled, 往下一筆
                        continue;
                    }
                    
                    if (null != menuItem.getParentMenuItem() && (null != menuItem.getParentMenuItem().getEnabled() &&  menuItem.getParentMenuItem().getEnabled().booleanValue()) )
                    {
                        // 子選單
                        Set<MenuItem> subMenuItems = userMenuItems.get(menuItem.getParentMenuItem());
                        if (null == subMenuItems)
                        {
                            subMenuItems = new TreeSet<MenuItem>(new Comparator<MenuItem>(){
                                public int compare(MenuItem o1, MenuItem o2) {
                                    int o1No = (null == o1.getOrderNo() ? -1 : o1.getOrderNo().intValue());
                                    int o2No = (null == o2.getOrderNo() ? -1 : o2.getOrderNo().intValue());
                                    if (o1No == o2No)
                                        return 0;
                                    else if (o1No > o2No)
                                        return 1;
                                    else return -1;
                                }}
                            );                            
                            userMenuItems.put(menuItem.getParentMenuItem(), subMenuItems);
                        }
                        if (!subMenuItems.contains(menuItem))
                            subMenuItems.add(menuItem);
                    }
                    else
                    {
                        // 主選單 或是，do nothing.
                        // 若是都沒有子選單，也不需要顯示主選單                       
                    }
                }
            }
        }

        return userMenuItems;
    }
    
    public static MenuItem getCurrentMenuItem()
    {
        if (null == _request || null == _request.get() )
            return null;
        
        ActionBean bean = (ActionBean) _request.get().getAttribute(StripesConstants.REQ_ATTR_ACTION_BEAN);
        String beanClassName = (null != bean ? bean.getClass().getSimpleName() : "");
        
        Map<MenuItem, Set<MenuItem>> menus =  getUserMenuItems();
        
        if (null == menus)
            return null;
        
        Set<MenuItem> keys = menus.keySet();
        
        for(Iterator<MenuItem> i = keys.iterator(); i.hasNext();)
        {
            MenuItem key = (MenuItem)i.next();
            
            if (beanClassName.equalsIgnoreCase(key.getActionBeanClass()))
            {
                return key;
            }
            
            Set<MenuItem> subMenus = menus.get(key);
            for(Iterator<MenuItem> j = subMenus.iterator(); j.hasNext();)
            {
                MenuItem sub = (MenuItem)j.next();
                if (beanClassName.equalsIgnoreCase(sub.getActionBeanClass()))
                {
                    return sub;
                }
            }
            
        }
        
        // 未找到
        return null;
        
    }
    
    public static String getCurrentMenuItemName()
    {
        MenuItem currentMenuItem = getCurrentMenuItem();
        if (null != currentMenuItem  && null != currentMenuItem.getActionName()){
            return currentMenuItem.getActionName();
        }
        return "";
    }
    
    /**
     * 是否為銀行群組
     * 
     * @return
     */
    public static boolean isBankGroup()
    {
        User user = getUser();
        if(null != user)
        {
            Group group = user.getGroup();
            if(null != group)
            {
                return Group.GROUP_TYPE_BANK.equals(group.getGroupType());
            }
        }
        return false;
    }


    /**
     * 是否為 ADMINISTRATOR 角色
     * @return
     */
    public static boolean isAdminRole()
    {
        boolean isAdmin = false;
        User user = getUser();
        if(null != user)
        {
            Iterator<Role> iterator = user.getRoles().iterator();
            while(iterator.hasNext())
            {
                Role role = iterator.next();

                if(ADMIN_ROLE.equals(role.getRoleNo()))
                {
                    isAdmin = true;
                    break;
                }
            }

        }

        return isAdmin;
    }

}
